local TitanXPStatus_Value=nil
TITAN_XPSTATUS_FREQUENCY=1;

-- Version information
local TitanXPStatusName = "TitanXPStatus";
local TitanXPStatusVersion = "3.3.1";
-- Version notes
-- toggle instead of display restedXP in options

local restedraw;
local restedpercent;

local totalkills = 0;
local avgxp = 0;
local totalxpgained = 0;
local xpgained = 0;
local neededkills = 0;

function TitanPanelXPStatusButton_OnLoad()
	this.registry={
		id="XPStatus",
        menuText="XP Status".."|cffffff80 v"..TitanXPStatusVersion..FONT_COLOR_CODE_CLOSE,
		buttonTextFunction="TitanPanelXPStatusButton_GetButtonText",
		tooltipTitle = "XP Info".."|cffffff80 v"..TitanXPStatusVersion..FONT_COLOR_CODE_CLOSE, 
		tooltipTextFunction = "TitanPanelXPStatusButton_GetTooltipText",
		frequency=TITAN_XPSTATUS_FREQUENCY,
		icon = TITAN_XPSTATUS_ICON,
		iconWidth = 16,
		savedVariables = {
			ShowIcon = 1,
			ShowLabelText = 1,
		}
	}

	this.timer = 0;	
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("PLAYER_XP_UPDATE");
	this:RegisterEvent("PLAYER_LEVEL_UP");
	this:RegisterEvent("UPDATE_EXHAUSTION");
	this:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN");
	this:RegisterEvent("TIME_PLAYED_MSG");
end

function TitanPanelXPStatusButton_OnShow()
	-- for a lack of better check at the moment
	-- TitanPanel_ButtonAdded is a global variable
	-- set to true only when a button has just been
	-- added to the panel
	if TitanPanel_ButtonAdded then
	  RequestTimePlayed();
	end
end

function TitanPanelXPStatusButton_OnEvent()
	if (event == "PLAYER_ENTERING_WORLD") then		
	  if (not this.sessionTime) then
				this.sessionTime = time();
		end
		if (not this.initXP) then
			this.initXP = UnitXP("player");
			this.accumXP = 0;
			this.sessionXP = 0;
			this.startSessionTime = time();
		end
		elseif (event == "TIME_PLAYED_MSG") then
			-- Remember play time
			this.totalTime = arg1;
			this.levelTime = arg2;
	elseif (event == "PLAYER_XP_UPDATE") then
		if (not this.initXP) then
			this.initXP = UnitXP("player");
			this.accumXP = 0;
			this.sessionXP = 0;
			this.startSessionTime = time();
		end
		this.sessionXP = UnitXP("player") - this.initXP + this.accumXP;
	elseif (event == "PLAYER_LEVEL_UP") then
	  this.levelTime = 0;
		this.accumXP = this.accumXP + UnitXPMax("player") - this.initXP;
		this.initXP = 0;
	end

	if(event=="CHAT_MSG_COMBAT_XP_GAIN") then
		for mobile_name, xp in string.gmatch(arg1, "(.+) dies, you gain (%d+) experience.") do
			xpgained = tonumber(xp)
			totalkills = totalkills + 1
			totalxpgained = totalxpgained + xpgained
		end
	end	
	if( (totalkills > 0) and (totalkills~=nil) ) then
			avgxp = floor(totalxpgained / totalkills * 100) / 100;
	end
	if( (avgxp > 0) and (avgxp~=nil) ) then
			neededkills = ( UnitXPMax("player") - UnitXP("player") ) / avgxp;
			neededkills = ceil(neededkills);
	end

	TitanPanelXPStatusButton_StatusBarBGUpdate();
	TitanPanelXPStatusButton_StatusBarUpdate();

	TitanPanelButton_UpdateButton("XPStatus");
	TitanPanelButton_UpdateTooltip();
end

function TitanPanelXPStatusButton_OnUpdate(elapsed)
	TITAN_XPSTATUS_FREQUENCY = TITAN_XPSTATUS_FREQUENCY - elapsed;
 if TITAN_XPSTATUS_FREQUENCY <=0 then
 TITAN_XPSTATUS_FREQUENCY = 1;
 TitanPanelButton_UpdateButton("XPStatus");
 TitanPanelButton_UpdateTooltip();
 end
 if (this.totalTime) then
		this.totalTime = this.totalTime + elapsed;
		this.levelTime = this.levelTime + elapsed;
 end
end

function TitanPanelXPStatusButton_GetButtonText(id)

	if TitanPanelXPStatusButton.startSessionTime == nil then
	return;
	end

	local button, id = TitanUtils_GetButton(id, true);
	local totalXP = UnitXPMax("player");
	local currentXP = UnitXP("player");
	local currentXPPercent = currentXP / totalXP * 100;
	local toLevelXP = totalXP - currentXP;
	local toLevelXPPercent = toLevelXP / totalXP * 100;	
	local sessionXP = button.sessionXP;
	local xpPerHour, xpPerHourText, timeToLevel, timeToLevelText;	
	local sessionTime = time() - TitanPanelXPStatusButton.startSessionTime;
	local levelTime = TitanPanelXPStatusButton.levelTime;
	local buttontext = "";
	local restedbuttontext = "";

	if (not StatusBar) or (not TitanPanelXPStatusButton:IsVisible()) then
		XPStatus:Hide()
	else
		XPStatus:Show()
	end

	local raw=GetXPExhaustion()
	local percent
	if raw then
		percent=floor((raw*100)/UnitXPMax("player"))
	else
		raw=0
		percent=0
	end

	if not Type then
		TitanXPStatus_Value=raw
	else
		TitanXPStatus_Value=percent.."%"
	end

		restedraw = raw;
		restedpercent = percent;

	if (UnitLevel("player") < 70) then

		if (ShowXP == 1) then
			toLevelXPText = toLevelXP;
			toLevelXPPercentText = toLevelXPPercent;

			buttontext = format(TITAN_XPSTATUS_TOLEVEL_XP_BUTTON, toLevelXPText)..
			format(TITAN_XPSTATUS_TOLEVELPERC_XP_BUTTON, toLevelXPPercentText)..
			" ";
			if (ShowRested == 1) then
				restedbuttontext = format(TITAN_XPSTATUS_BUTTON_TEXT_RESTED,TitanUtils_GetHighlightText(TitanXPStatus_Value));
			end

			-- supports turning off labels
			if (ShowRested == 1) then
				return TITAN_XPSTATUS_TOLEVEL_XP_LABEL, buttontext, TITAN_XPSTATUS_BUTTON_TEXT_LABEL, restedbuttontext;
			else
				return TITAN_XPSTATUS_TOLEVEL_XP_LABEL, buttontext;
			end
		else	
			currentXPText = currentXP;
			currentXPPercentText = currentXPPercent;
			totalXPText = totalXP;
		
			buttontext = format(TITAN_XPSTATUS_CURRENT_XP_BUTTON, currentXPText)..
			format(TITAN_XPSTATUS_MAX_XP_BUTTON, totalXPText)..
			format(TITAN_XPSTATUS_CURRENTPERC_XP_BUTTON, currentXPPercentText)..
			" ";
			if (ShowRested == 1) then
				restedbuttontext = format(TITAN_XPSTATUS_BUTTON_TEXT_RESTED,TitanUtils_GetHighlightText(TitanXPStatus_Value));
			end

			-- supports turning off labels
			if (ShowRested == 1) then
				return TITAN_XPSTATUS_CURRENT_XP_LABEL, buttontext, TITAN_XPSTATUS_BUTTON_TEXT_LABEL, restedbuttontext;
			else
				return TITAN_XPSTATUS_CURRENT_XP_LABEL, buttontext;
			end
		end
	else
		return TITAN_XPSTATUS_TOLEVEL_XP_LABEL, TITAN_XPSTATUS_LVL70REACHED_LABEL..FONT_COLOR_CODE_CLOSE;
	end
end

function TitanPanelXPStatusButton_GetTooltipText()

	local xp = { 0, 400, 1300, 2700, 4800, 7600, 11200, 15700, 21100, 27600,
                35200, 43900, 53700, 64700, 77000, 90600, 105600, 122000, 139800, 159100,
		        179900, 202300, 226300, 251800, 279000, 307900, 338400, 370600, 404500, 440800,
		        479600, 521200, 565800, 613800, 665200, 720200, 778900, 841300, 907500, 977700,
		        1052000, 1130500, 1213300, 1300400, 1392000, 1487300, 1588300, 1694100, 1804800, 1920500,
		        2041400, 2167500, 2299000, 2436000, 2578500, 2726700, 2880700, 3040600, 3206400, 3378400,
		        3872400, 4447100, 5061500, 5711800, 6394100, 7104300, 7838400, 8592100, 9361000, 10140800 }

	local totalTime = TitanPanelXPStatusButton.totalTime;
	local totalXP = UnitXPMax("player");
	local sessionTime = time() - TitanPanelXPStatusButton.startSessionTime;
	local levelTime = TitanPanelXPStatusButton.levelTime;
  local CurrentLevel = UnitLevel("player");
	local XPToCurrentLevel = xp[CurrentLevel];
	local currentXP = UnitXP("player");
	local totallvlXP = currentXP + XPToCurrentLevel;
	local toLevelXP = totalXP - currentXP;
	local currentXPPercent = currentXP / totalXP * 100;
	local toLevelXPPercent = toLevelXP / totalXP * 100;
	local xpPerHourThisLevel = currentXP / levelTime * 3600;
	local xpPerHourThisSession = this.sessionXP / sessionTime * 3600;
	local estTimeToLevelThisLevel = TitanUtils_Ternary((currentXP == 0), -1, toLevelXP / currentXP * levelTime);
	local estTimeToLevelThisSession = TitanUtils_Ternary((this.sessionXP == 0), -1, toLevelXP / this.sessionXP * sessionTime);
	local lvl70XP = xp[70];
	local lvl70XPneeded = lvl70XP - totallvlXP;
	local lvl70XPneededPercent = lvl70XPneeded / lvl70XP * 100;

	if (CurrentLevel < 70) then
		return ""..
		format(TITAN_XPSTATUS_TOOLTIP_SHIFTCLICK).."\n"..
        "\n"..
        format(TITAN_XPSTATUS_LVL70XP, lvl70XPneeded, lvl70XPneededPercent).."\n"..
        format(TITAN_XPSTATUS_TOOLTIP_RESTED, restedraw, restedpercent).."\n"..
        "\n"..
        format(TITAN_XPSTATUS_TOTAL_XP, totalXP).."\n"..
        format(TITAN_XPSTATUS_LEVEL_XP_VALUEPERCENT, currentXP, currentXPPercent).."\n".. 
		format(TITAN_XPSTATUS_TOLEVEL_XP_VALUEPERCENT, toLevelXP, toLevelXPPercent).."\n"..
		format(TITAN_XPSTATUS_SESSION_XP, this.sessionXP).."\n"..
		"\n"..
		format(TITAN_XPSTATUS_AVGXP,avgxp).."\n"..
		format(TITAN_XPSTATUS_TOTALKILLS,totalkills).."\n"..
		format(TITAN_XPSTATUS_NEEDEDKILLS,neededkills).."\n"..
		"\n"..
		format(TITAN_XPSTATUS_TOTAL_TIME_PLAYED, TitanUtils_GetAbbrTimeText(totalTime)).."\n"..
		format(TITAN_XPSTATUS_LEVEL_TIME_PLAYED, TitanUtils_GetAbbrTimeText(levelTime)).."\n"..
		format(TITAN_XPSTATUS_SESSION_TIME_PLAYED, TitanUtils_GetAbbrTimeText(sessionTime)).."\n"..
		"\n"..
		format(TITAN_XPSTATUS_PER_HOUR_LEVEL, xpPerHourThisLevel).."\n"..
		format(TITAN_XPSTATUS_PER_HOUR_SESSION, xpPerHourThisSession).."\n"..
		format(TITAN_XPSTATUS_EST_TIME_TO_LEVEL_LEVEL_RATE, TitanUtils_GetAbbrTimeText(estTimeToLevelThisLevel)).."\n"..
		format(TITAN_XPSTATUS_EST_TIME_TO_LEVEL_SESSION_RATE, TitanUtils_GetAbbrTimeText(estTimeToLevelThisSession));
	else
		return ""..
		"|cff9932cc"..TITAN_XPSTATUS_LVL70REACHED..FONT_COLOR_CODE_CLOSE.."\n".."\n"..
		format(TITAN_XPSTATUS_TOTAL_TIME_PLAYED, TitanUtils_GetAbbrTimeText(totalTime)).."\n"..
		format(TITAN_XPSTATUS_LEVEL_TIME_PLAYED, TitanUtils_GetAbbrTimeText(levelTime)).."\n"..
		format(TITAN_XPSTATUS_SESSION_TIME_PLAYED, TitanUtils_GetAbbrTimeText(sessionTime));
	end
end

function TitanPanelRightClickMenu_PrepareXPStatusMenu()
	local id="XPStatus"
	local info
	TitanPanelRightClickMenu_AddTitle(TitanPlugins[id].menuText)

	info={}
	info.text=TITAN_XPSTATUS_MENU_SHOW_RAW
	info.func=function()
		Type=nil
		TitanPanelButton_UpdateButton("XPStatus")
	end
	info.checked=TitanUtils_Toggle(Type)
	UIDropDownMenu_AddButton(info)

	info={}
	info.text=TITAN_XPSTATUS_MENU_SHOW_PERCENT
	info.func=function()
		Type=1
		TitanPanelButton_UpdateButton("XPStatus")
	end
	info.checked=Type
	UIDropDownMenu_AddButton(info)

	info = {};
	info.text = TITAN_XPSTATUS_MENU_SHOWRESTED;
	info.func = TitanPanelXPStatusButton_ShowRested;
	info.checked = TitanUtils_Toggle(ShowRested);
	UIDropDownMenu_AddButton(info);

	TitanPanelRightClickMenu_AddSpacer();

	info = {};
	info.text = TITAN_XPSTATUS_MENU_SHOW_XPHR_THIS_SESSION;
	info.func = TitanPanelXPStatusButton_ShowXP;
	info.checked = ShowXP;
	UIDropDownMenu_AddButton(info);

	info = {};
	info.text = TITAN_XPSTATUS_MENU_SHOW_XPHR_THIS_LEVEL;
	info.func = TitanPanelXPStatusButton_ShowXPLevel;
	info.checked = TitanUtils_Toggle(ShowXP);
	UIDropDownMenu_AddButton(info);

	TitanPanelRightClickMenu_AddSpacer();

	info = {};
	info.text = TITAN_XPSTATUS_MENU_SHOW_STATUSBAR;
	info.func = TitanPanelXPStatusButton_ShowStatus;
	info.checked = StatusBar;
	UIDropDownMenu_AddButton(info);

	info = {};
	info.text = TITAN_XPSTATUS_MENU_HIDE_STATUSBAR;
	info.func = TitanPanelXPStatusButton_HideStatus;
	info.checked = TitanUtils_Toggle(StatusBar);
	UIDropDownMenu_AddButton(info);
	
	TitanPanelRightClickMenu_AddSpacer();
	
	TitanPanelRightClickMenu_AddCommand(TITAN_XPSTATUS_MENU_REFRESH_PLAYED, "XPStatus", "TitanPanelXPStatusButton_RefreshPlayed");

	TitanPanelRightClickMenu_AddSpacer();

	TitanPanelRightClickMenu_AddToggleLabelText("XPStatus");

	TitanPanelRightClickMenu_AddSpacer();

	TitanPanelRightClickMenu_AddCommand(TITAN_PANEL_MENU_HIDE,id,TITAN_PANEL_MENU_FUNC_HIDE)
end

function TitanPanelXPStatusButton_ShowXP()
	ShowXP = 1;
	TitanPanelButton_UpdateButton("XPStatus");
end

function TitanPanelXPStatusButton_ShowXPLevel()
	ShowXP = nil;
	TitanPanelButton_UpdateButton("XPStatus");
end

function TitanPanelXPStatusButton_ShowStatus()
	StatusBar = 1;
	TitanPanelButton_UpdateButton("XPStatus");
end

function TitanPanelXPStatusButton_HideStatus()
	StatusBar = nil;
	TitanPanelButton_UpdateButton("XPStatus");
end

function TitanPanelXPStatusButton_ShowRested()
    if ( ShowRested == 1) then
        ShowRested = 0;
    else
        ShowRested = 1;
    end
	TitanPanelButton_UpdateButton("XPStatus");
end

function TitanPanelXPStatusButton_OnClick()
	local totalXP = UnitXPMax("player");
	local currentXP = UnitXP("player");
	local toLevelXP = totalXP - currentXP;
	local currentXPPercent = currentXP / totalXP * 100;
	local toLevelXPPercent = toLevelXP / totalXP * 100;
	local currentpercent;
	local levelpercent;
	local level = UnitLevel("player");
	local nextlevel = level + 1;

	currentpercent=floor(currentXPPercent);
	levelpercent=floor(toLevelXPPercent);

	if (IsShiftKeyDown()) then
		if (UnitLevel("player") < 70) then
			if (not chatFrame) then
				chatFrame = DEFAULT_CHAT_FRAME;
			end

			chatType = chatFrame.editBox.chatType;

			if (ShowXP == 1) then
				if (ChatFrameEditBox:IsVisible()) then
					ChatFrameEditBox:Insert("XPtoLvl "..nextlevel..": "..toLevelXP.." ("..levelpercent.."%) RestedXP: "..restedraw.." ("..restedpercent.."%) AvgXP: "..avgxp);
				else
					SendChatMessage("XPtoLvl "..nextlevel..": "..toLevelXP.." ("..levelpercent.."%) RestedXP: "..restedraw.." ("..restedpercent.."%) AvgXP: "..avgxp, chatType);
				end
			else
				if (ChatFrameEditBox:IsVisible()) then
					ChatFrameEditBox:Insert("XP/T: "..currentXP.."/"..totalXP.." ("..currentpercent.."%) RestedXP: "..restedraw.." ("..restedpercent.."%) AvgXP: "..avgxp);
				else
					SendChatMessage("XP/T: "..currentXP.."/"..totalXP.." ("..currentpercent.."%) RestedXP: "..restedraw.." ("..restedpercent.."%) AvgXP: "..avgxp, chatType);
				end
			end
		end
	end
end

function TitanPanelXPStatusButton_StatusBarBGUpdate()
	local maxValue = UnitXPMax("player");

	XPStatusBG:SetMinMaxValues(0, maxValue);
	XPStatusBG:SetValue(maxValue);
end

function TitanPanelXPStatusButton_StatusBarUpdate()
	local currentValue = UnitXP("player");
	local maxValue = UnitXPMax("player");

	XPStatus:SetMinMaxValues(0, maxValue);
	XPStatus:SetValue(currentValue);
end

function TitanPanelXPStatusButton_RefreshPlayed()
  RequestTimePlayed();
end